/*
 * Copyright (c) 2018, apexes.net. All rights reserved.
 *
 *         http://www.apexes.net
 *
 */
package net.apexes.commons.lang;

/**
 * 
 * @author <a href="mailto:hedyn@foxmail.com">HeDYn</a>
 * 
 * @param <T>
 */
public interface ValueEnum<T> {
	
	T value();

	boolean eqValue(T value);
	
	boolean isUnknown();
	
	void setUnknownValue(T value);
	
	/**
     * 
     * @author <a href="mailto:hedyn@foxmail.com">HeDYn</a>
     *
     * @param <T>
     */
    final class Helper<T> {
    	
    	public static <T> Helper<T> valueHelper(T value) {
    		return new Helper<T>(value);
    	}
    	
    	public static <T> Helper<T> unknownHelper() {
    		return new Helper<T>();
    	}

        private final T value;
        private final boolean unknown;
        private T unknownValue;

        private Helper(T value) {
            this.value = value;
            this.unknown = false;
        }

        private Helper() {
        	this.value = null;
            this.unknown = true;
        }
        
        public T value() {
            return unknown ? unknownValue : value;
        }

        public <E extends Enum<E> & ValueEnum<T>> boolean equalsValue(E valueEnum, T value) {
            return ValueEnums.eqValue(valueEnum, value);
        }

        public boolean isUnknown() {
            return unknown;
        }

        public void setUnknownValue(T value) {
            if (unknown) {
                this.unknownValue = value;
            } else {
                throw new UnsupportedOperationException("Must be unknown enum.");
            }
        }
        
    }

}
